package jwtUtil

import (
	"errors"
	"log"
	"time"

	"github.com/golang-jwt/jwt/v4"
)

var (
	key = []byte("gin-learn")

	TokenExpired     = errors.New("token is expired")
	TokenNotValidYet = errors.New("token not active yet")
	TokenMalformed   = errors.New("that's not even a token")
	TokenInvalid     = errors.New("couldn't handle this token")
)

// StandardClaims
// Audience  string `json:"aud,omitempty"`
// ExpiresAt int64  `json:"exp,omitempty"`
// Id        string `json:"jti,omitempty"`
// IssuedAt  int64  `json:"iat,omitempty"`
// Issuer    string `json:"iss,omitempty"`
// NotBefore int64  `json:"nbf,omitempty"`
// Subject   string `json:"sub,omitempty"`

func GetToken(username string) string {
	// 创建token结构体
	claims := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{
		"username": username,                 // 自己添加参数
		"iss":      "x-client",               // 签发给谁
		"nbf":      time.Now().Unix(),        // token 有效的开始时间
		"exp":      time.Now().Unix() + 60*5, // token 失效时间
	})

	// 调用加密算法 生成token
	signedString, _ := claims.SignedString(key)
	log.Printf("signedString=%s\n", signedString)
	return signedString
}

// VerifyToken 根据token字符串解析claims结构体
func VerifyToken(signString string) (*jwt.MapClaims, error) {
	token, err := jwt.ParseWithClaims(signString, &jwt.MapClaims{}, func(token *jwt.Token) (interface{}, error) {
		return key, nil
	})

	if err != nil {
		if ve, ok := err.(*jwt.ValidationError); ok {
			if ve.Errors&jwt.ValidationErrorMalformed != 0 {
				return nil, TokenMalformed
			} else if ve.Errors&jwt.ValidationErrorExpired != 0 {
				// Token is expired
				return nil, TokenExpired
			} else if ve.Errors&jwt.ValidationErrorNotValidYet != 0 {
				return nil, TokenNotValidYet
			} else {
				return nil, TokenInvalid
			}
		}
	}

	if token != nil {
		if claims, ok := token.Claims.(*jwt.MapClaims); ok && token.Valid {
			return claims, nil
		}
	}
	return nil, TokenInvalid

}
